home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Mark Pilgrim / Dialectic 1.2 / source / Dialectic ƒ / Shell ƒ / graphics.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-30  |  12.3 KB  |  322 lines  |  [TEXT/KAHL]

  1. /**********************************************************************\
  2.  
  3. File:        graphics.c
  4.  
  5. Purpose:    This module handles opening/closing/updating all windows:
  6.             this includes manipulating offscreen GWorlds & bitmaps
  7.             for fun and profit.
  8.  
  9. \**********************************************************************/
  10.  
  11. #include "graphics.h"
  12. #include "about.h"
  13. #include "about MSG.h"
  14. #include "help.h"
  15. #include "dialogs.h"
  16. #include "error.h"
  17. #include "menus.h"
  18. #include "environment.h"
  19. #include "prefs.h"
  20. #include "program globals.h"
  21.  
  22. WindowPtr        gTheWindow[NUM_WINDOWS];            /* windowptr of nth window */
  23. ExtendedWindowDataHandle
  24.                 gTheWindowData[NUM_WINDOWS];        /* handle to nth window data struct */
  25.  
  26. /* internal global variables for use by graphics.c only */
  27. static    Rect        gBoundsRect[NUM_WINDOWS];        /* rectangle of offscreen bitmap */
  28. static    Rect        gMainScreenBounds;                /* bounds of main monitor */
  29. static    GWorldPtr    gTheGWorld[NUM_WINDOWS];        /* offscreen graphics world */
  30. static    int            gOffscreenDepth[NUM_WINDOWS];    /* pixel depth of offscreen GWorld */
  31. static    Ptr            gBWBitMap[NUM_WINDOWS];            /* offscreen bitmap for B/W machines */
  32. static    GrafPort    gBWGrafPort[NUM_WINDOWS];        /* offscreen grafport "  "     "     */
  33. static    GrafPtr        gBWGrafPtr[NUM_WINDOWS];        /* offscreen grafptr  "  "     "     */
  34.  
  35.  
  36. Boolean InitTheGraphics(void)
  37. {
  38.     int                i;
  39.     
  40.     GetMainScreenBounds();
  41.     
  42.     for (i=0; i<NUM_WINDOWS; i++)
  43.     {
  44.         /* nothing is inited; if there's an error later on, we'll know how much to */
  45.         /* clean up in ShutDownTheGraphics() */
  46.         gTheWindow[i]=gTheGWorld[i]=gTheWindowData[i]=0L;
  47.     }
  48.     
  49.     for (i=0; i<NUM_WINDOWS; i++)
  50.     {
  51.         gTheWindowData[i]=(ExtendedWindowDataHandle)NewHandle(sizeof(ExtendedWindowDataRec));
  52.         if (gTheWindowData[i]==0L)                            /* return if error */
  53.             return FALSE;
  54.         
  55.         (**(gTheWindowData[i])).offscreenNeedsUpdate=TRUE;    /* offscreen not inited */
  56.         (**(gTheWindowData[i])).windowIndex=i;                /* so we can retrieve it O(1) */
  57.     }
  58.     
  59.     /* set window dispatch routines */
  60.     (**(gTheWindowData[kAbout])).dispatchProc=AboutBoxDispatch;        /* see about.c */
  61.     (**(gTheWindowData[kHelp])).dispatchProc=HelpWindowDispatch;    /* see help.c */
  62.     (**(gTheWindowData[kAboutMSG])).dispatchProc=AboutMSGBoxDispatch;/* see about MSG.c */
  63.     
  64.     /* call window dispatch routines with "startup" message */
  65.     ((**(gTheWindowData[kAbout])).dispatchProc)(gTheWindowData[kAbout], kStartup, 0L);
  66.     ((**(gTheWindowData[kHelp])).dispatchProc)(gTheWindowData[kHelp], kStartup, 0L);
  67.     ((**(gTheWindowData[kAboutMSG])).dispatchProc)(gTheWindowData[kAboutMSG], kStartup, 0L);
  68.     
  69.     return TRUE;
  70. }
  71.  
  72. void OpenTheWindow(int index)
  73. {
  74.     if (!gTheWindow[index])        /* if window exists, we'll just update it (see below) */
  75.     {
  76.         if (((**(gTheWindowData[index])).dispatchProc)    /* call window's dispatch to */
  77.                 (gTheWindowData[index], kInitialize, 0L)==kFailure)    /* initialize it */
  78.         {        /* default is to center window on main screen */
  79.             (**(gTheWindowData[index])).initialTopLeft.h =
  80.                 gMainScreenBounds.left + (((gMainScreenBounds.right -
  81.                 gMainScreenBounds.left) - (**(gTheWindowData[index])).windowWidth) / 2);
  82.             (**(gTheWindowData[index])).initialTopLeft.v =
  83.                 gMainScreenBounds.top + (((gMainScreenBounds.bottom -
  84.                 gMainScreenBounds.top) - (**(gTheWindowData[index])).windowHeight) / 2);
  85.         }
  86.         
  87.         (**(gTheWindowData[index])).windowBounds.left=
  88.             (**(gTheWindowData[index])).initialTopLeft.h;
  89.         
  90.         (**(gTheWindowData[index])).windowBounds.top=
  91.             (**(gTheWindowData[index])).initialTopLeft.v;
  92.             
  93.         if (((**(gTheWindowData[index])).windowType==noGrowDocProc) ||
  94.             ((**(gTheWindowData[index])).windowType==documentProc) ||
  95.             ((**(gTheWindowData[index])).windowType==movableDBoxProc) ||
  96.             ((**(gTheWindowData[index])).windowType==zoomDocProc) ||
  97.             ((**(gTheWindowData[index])).windowType==zoomNoGrow) ||
  98.             ((**(gTheWindowData[index])).windowType==rDocProc))
  99.                 (**(gTheWindowData[index])).windowBounds.top += 9;    /* compensate for title */
  100.         
  101.         /* don't put window over menu bar */
  102.         if ((**(gTheWindowData[index])).windowBounds.top < GetMBarHeight()+1)
  103.             (**(gTheWindowData[index])).windowBounds.top = GetMBarHeight()+1;
  104.         
  105.         (**(gTheWindowData[index])).windowBounds.bottom =
  106.             (**(gTheWindowData[index])).windowBounds.top +
  107.             (**(gTheWindowData[index])).windowHeight;
  108.         
  109.         (**(gTheWindowData[index])).windowBounds.right =
  110.             (**(gTheWindowData[index])).windowBounds.left +
  111.             (**(gTheWindowData[index])).windowWidth;
  112.         
  113.         if (gHasColorQD)
  114.         {
  115.             HLock(gTheWindowData[index]);    /* important!  NewCWindow may move memory */
  116.             /* create the color window with our specs, see IM Essentials 4-79ff */
  117.             gTheWindow[index] = NewCWindow(0L, &((**(gTheWindowData[index])).windowBounds),
  118.                 (**(gTheWindowData[index])).windowTitle, FALSE,
  119.                 (**(gTheWindowData[index])).windowType, (WindowPtr)-1L,
  120.                 (**(gTheWindowData[index])).hasCloseBox,
  121.                 (unsigned long)gTheWindowData[index]);
  122.             HUnlock(gTheWindowData[index]);    /* no sense keeping it locked now */
  123.         }
  124.         else
  125.         {
  126.             HLock(gTheWindowData[index]);    /* important!  NewWindow may move memory */
  127.             /* create the B/W window with our specs, see IM Essentials 4-82ff */
  128.             gTheWindow[index] = NewWindow(0L, &((**(gTheWindowData[index])).windowBounds),
  129.                 (**(gTheWindowData[index])).windowTitle, FALSE,
  130.                 (**(gTheWindowData[index])).windowType, (WindowPtr)-1L,
  131.                 (**(gTheWindowData[index])).hasCloseBox,
  132.                 (unsigned long)gTheWindowData[index]);
  133.             HUnlock(gTheWindowData[index]);    /* no sense keeping it locked now */
  134.         }
  135.     }
  136.     
  137.     if (gTheWindow[index])
  138.     {
  139.         ShowWindow(gTheWindow[index]);            /* immediately show this new window */
  140.         SelectWindow(gTheWindow[index]);        /* immediately select this new window */
  141.         /* call window's dispatch routine to alert it that it's open now */
  142.         ((**(gTheWindowData[index])).dispatchProc)(gTheWindowData[index], kOpen, 0L);
  143.         SetPort(gTheWindow[index]);                /* important! */
  144.         UpdateTheWindow(gTheWindowData[index]);    /* immediately update this new window */
  145.     }
  146.     else HandleError(kNoMemory, FALSE);            /* if unsuccessful, display error */
  147. }
  148.  
  149. void GetMainScreenBounds(void)
  150. {
  151.     gMainScreenBounds = screenBits.bounds;        /* low-mem global */
  152.     gMainScreenBounds.top += GetMBarHeight();    /* don't include menu bar */
  153. }
  154.  
  155. int GetWindowDepth(ExtendedWindowDataHandle theData)
  156. {
  157.     int                index;
  158.     
  159.     index=(**theData).windowIndex;
  160.     /* if Color Quickdraw is not available, the depth must be 1. */
  161.     /* if Color Quickdraw is available and the window exists, return the window's
  162.        GWorld's graphics device's pixel map's pixel depth */
  163.     /* if Color Quickdraw is available and the window does not exist, return the
  164.        pixel depth of the main screen */
  165.     return (gHasColorQD) ? ((gTheWindow[index]) ?
  166.             (**(**(GetGWorldDevice(gTheGWorld[index]))).gdPMap).pixelSize :
  167.             (**(**GetMainDevice()).gdPMap).pixelSize) : 1;
  168. }
  169.  
  170. void UpdateTheWindow(ExtendedWindowDataHandle theData)
  171. {
  172.     int                index;
  173.     GWorldPtr        currentGWorld;
  174.     GDHandle        currentGDHandle;
  175.     long            offRowBytes, sizeOfOff;
  176.     
  177.     index=(**theData).windowIndex;
  178.     gBoundsRect[index]=gTheWindow[index]->portRect;
  179.     OffsetRect(&gBoundsRect[index], -gBoundsRect[index].left, -gBoundsRect[index].top);
  180.  
  181.     if (gHasColorQD)    /* w/o Color Quickdraw, GWorlds may not be supported */
  182.     {
  183.         if (gTheGWorld[index]==0L)        /* create new graphics world if none exists */
  184.         {
  185.             /* try to create new graphics world; display error if unsuccessful */
  186.             if (NewGWorld(&gTheGWorld[index], 0, &gBoundsRect[index], 0L, 0L, 0)!=0)
  187.             {
  188.                 HandleError(kNoMemory, FALSE);
  189.                 return;
  190.             }
  191.             gOffscreenDepth[index]=GetWindowDepth(theData);    /* keep track of pixel depth */
  192.             NoPurgePixels(GetGWorldPixMap(gTheGWorld[index]));    /* never purge our pixmap! */
  193.         }
  194.         
  195.         GetGWorld(¤tGWorld, ¤tGDHandle);    /* get current settings */
  196.         LockPixels(GetGWorldPixMap(gTheGWorld[index]));    /* important!  copybits may move mem */
  197.         /* update offscreen graphics world, compensating for change in pixel depth */
  198.         UpdateGWorld(&gTheGWorld[index], 0, &gBoundsRect[index], 0L, 0L, 0);
  199.         SetGWorld(gTheGWorld[index], 0L);                /* set to our offscreen gworld */
  200.  
  201.         if (gOffscreenDepth[index]!=GetWindowDepth(theData))    /* if pixel depth changed */
  202.         {
  203.             gOffscreenDepth[index]=GetWindowDepth(theData);        /* save new depth */
  204.             (**theData).offscreenNeedsUpdate=TRUE;                /* we'll need to redraw */
  205.         }
  206.     }
  207.     else    /* deal with (guaranteed) B/W bitmaps manually */
  208.     {
  209.         if (gBWGrafPtr[index]==0L)    /* create new offscreen bitmap if none exists */
  210.         {
  211.             gBWGrafPtr[index]=&gBWGrafPort[index];
  212.             OpenPort(gBWGrafPtr[index]);    /* make a new port */
  213.             
  214.             /* calculate the size of the offscreen bitmap from the boundsrect */
  215.             offRowBytes=(((gBoundsRect[index].right-gBoundsRect[index].left)+15)>>4)<<1;
  216.             sizeOfOff=(long)(gBoundsRect[index].bottom-gBoundsRect[index].top)*offRowBytes;
  217.             
  218.             gBWBitMap[index]=NewPtr(sizeOfOff);        /* allocate space for bitmap */
  219.             if (gBWBitMap[index]==0L)                /* abort if unsuccessful */
  220.             {
  221.                 ClosePort(gBWGrafPtr[index]);        /* cleaning up... */
  222.                 gBWGrafPtr[index]=0L;
  223.                 HandleError(kNoMemory, FALSE);        /* displaying error... */
  224.                 return;                                /* and aborting... */
  225.             }
  226.             
  227.             gBWGrafPort[index].portBits.baseAddr=gBWBitMap[index];    /* --> our bitmap */
  228.             gBWGrafPort[index].portBits.rowBytes=offRowBytes;        /* bitmap size */
  229.             gBWGrafPort[index].portBits.bounds=                        /* bitmap bounds */
  230.                 gBWGrafPort[index].portRect=gBoundsRect[index];            
  231.         }
  232.         
  233.         SetPort(gBWGrafPtr[index]);                    /* set port for subsequent drawing */
  234.     }    
  235.     
  236.     if ((**theData).offscreenNeedsUpdate)            /* if we need to redraw */
  237.     {
  238.         (**theData).offscreenNeedsUpdate=FALSE;        /* not anymore */
  239.         /* call window's dispatch and tell it to redraw itself */
  240.         ((**theData).dispatchProc)(theData, kUpdate, GetWindowDepth(theData));
  241.     }
  242.     
  243.     if (gHasColorQD)
  244.         SetGWorld(currentGWorld, currentGDHandle);    /* restore old settings */
  245.     
  246.     SetPort(gTheWindow[index]);                        /* set to window to draw to */
  247.     /* copy offscreen bitmap from graphics world or bitmap to onscreen window */
  248.     CopyBits(gHasColorQD ? &(((GrafPtr)gTheGWorld[index])->portBits) :
  249.                 &(gBWGrafPtr[index]->portBits), &(gTheWindow[index]->portBits),
  250.                 &gBoundsRect[index], &gBoundsRect[index], 0, 0L);
  251.     
  252.     if (gHasColorQD)
  253.         UnlockPixels(GetGWorldPixMap(gTheGWorld[index]));    /* remember we locked these? */
  254.     
  255.     ValidRect(&(gTheWindow[index]->portRect));        /* so we don't reupdate */
  256. }
  257.  
  258. Boolean CloseTheWindow(ExtendedWindowDataHandle theData)
  259. {
  260.     int                index;
  261.     
  262.     index=(**theData).windowIndex;
  263.     
  264.     /* if the window's dispatch cancels the close, abort */
  265.     if (((**theData).dispatchProc)(theData, kClose, 0L)==kCancel)
  266.         return FALSE;
  267.     
  268.     DisposeWindow(gTheWindow[index]);    /* get rid of the actual window in memory */
  269.     gTheWindow[index]=0L;                /* so _we_ know the window doesn't exist */
  270.     
  271.     /* tell window's dispatch that it's disposed of now */
  272.     ((**theData).dispatchProc)(theData, kDispose, 0L);
  273.     
  274.     return TRUE;    /* successful close */
  275. }
  276.  
  277. void DrawThePicture(PicHandle *thePict, int whichPict, int x, int y)
  278. /* a standard routine for loading a picture (if necessary) and then drawing it */
  279. {
  280.     Rect            temp;
  281.     
  282.     if (*thePict==0L)        /* get it if it doesn't exist */
  283.         *thePict=(PicHandle)GetPicture(whichPict);
  284.     
  285.     HLock(*thePict);        /* lock it down for dereferencing to get picture bounds */
  286.     temp.top=y;
  287.     temp.left=x;
  288.     temp.bottom=temp.top+(***thePict).picFrame.bottom-(***thePict).picFrame.top;
  289.     temp.right=temp.left+(***thePict).picFrame.right-(***thePict).picFrame.left;
  290.     DrawPicture(*thePict, &temp);    /* draw picture at (x,y) */
  291.     HUnlock(*thePict);        /* unlock for better memory management */
  292. }
  293.  
  294. void ReleaseThePict(PicHandle *thePict)
  295. {
  296.     if (*thePict!=0L)    /* if exists, release it */
  297.     {
  298.         ReleaseResource(*thePict);
  299.         *thePict=0L;    /* so _we_ know it's released */
  300.     }
  301. }
  302.  
  303. void ShutDownTheGraphics(void)
  304. {
  305.     int                i;
  306.     
  307.     /* send shutdown messages to the shell's windows */
  308.     ((**(gTheWindowData[kAbout])).dispatchProc)(gTheWindowData[kAbout], kShutdown, 0L);
  309.     ((**(gTheWindowData[kHelp])).dispatchProc)(gTheWindowData[kHelp], kShutdown, 0L);
  310.     ((**(gTheWindowData[kAboutMSG])).dispatchProc)(gTheWindowData[kAboutMSG], kShutdown, 0L);
  311.     
  312.     for (i=0; i<NUM_WINDOWS; i++)                /* technically, none of this cleanup */
  313.     {                                            /* is necessary, since these are all */
  314.         if (gTheGWorld[i]!=0L)                    /* in the application heap, which is */
  315.             DisposeGWorld(gTheGWorld[i]);        /* about to get trashed when we quit */
  316.         if (gTheWindowData[i]!=0L)                /* anyway, but it's still good to Do */
  317.             DisposeHandle(gTheWindowData[i]);    /* The Right Thing™ even if it kills */
  318.         if (gTheWindow[i]!=0L)                    /* you in the process (:             */
  319.             DisposeWindow(gTheWindow[i]);
  320.     }
  321. }
  322.